Skip to content

Use unmodified official ClangFormat configuration as base formatter configuration #1324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 16, 2022
Merged

Use unmodified official ClangFormat configuration as base formatter configuration #1324

merged 4 commits into from
Aug 16, 2022

Conversation

per1234
Copy link
Contributor

@per1234 per1234 commented Aug 15, 2022

The Arduino IDE's "Auto Format" feature is configured to produce the standard Arduino sketch formatting style by default.

The Arduino IDE editor's default settings are compliant with that style. However, the user may adjust the editor settings. In this case, the Arduino IDE automatically adjusts the "Auto Format" configuration to align with the user's preferences.

The formatter configuration is consumed by several other projects in addition to the Arduino IDE. For this reason, the configuration is hosted and maintained in a centralized location, from which it is pulled by all projects that use it.

Motivation

The adjustment of the Arduino IDE formatter configuration according to the editor settings is integrated into the configuration object itself:

TabWidth,
UseCRLF: false,
UseTab,

This means that the standardized configuration has to be modified each time it is pulled in to sync from the upstream source.

Change description

Move the adjustment code out of the base formatter configuration object to allow syncs to be done via a pure copy/paste replacement.

Other information

Example of a configuration sync: #1285

Reviewer checklist

  • PR addresses a single concern.
  • The PR has no duplicates (please search among the Pull Requests before creating one)
  • PR title and description are properly filled.
  • Docs have been added / updated (for bug fixes / features)

@per1234 per1234 added type: enhancement Proposed improvement topic: code Related to content of the project itself labels Aug 15, 2022
@per1234 per1234 requested a review from kittaakos August 15, 2022 17:55
@per1234 per1234 self-assigned this Aug 15, 2022
@kittaakos
Copy link
Contributor

Change description

Move the adjustment code out of the base formatter configuration object to allow syncs to be done via a pure copy/paste replacement.

We could move the default formatter JSON into a dedicated file if it helps the synchronization. Consider the following folder structure:

arduino-ide-extension/src/node/clang-formatter.ts
arduino-ide-extension/src/node/default-formatter-config.json (<-- you can pick a better name if you want)

and then from code:

function styleJson({
  TabWidth,
  UseTab,
}: ClangFormatOptions): Record<string, unknown> {
  // Source: https://github.com/arduino/tooling-project-assets/tree/main/other/clang-format-configuration
  const defaultConfig = require('./default-formatter-config.json'); // 1. require the JSON
  return {
    ...defaultConfig,
    TabWidth, // 2. override the default values with the user-defined ones
    UseTab,
  };
}
  1. Require the JSON content with require. To do this, we have to add "resolveJsonModule": true to arduino-ide-extension/tsconfig.json,
  2. Use the spread operator to merge in the user-defined values. (See the docs here).

I think this will make the config synchronization easier and we do not have to touch code when we update the config. What do you think?

Click here, I created and formatted the JSON so that you can copy-paste it into a .json file

{
    "AccessModifierOffset": -2,
    "AlignAfterOpenBracket": "Align",
    "AlignArrayOfStructures": "None",
    "AlignConsecutiveAssignments": "None",
    "AlignConsecutiveBitFields": "None",
    "AlignConsecutiveDeclarations": "None",
    "AlignConsecutiveMacros": "None",
    "AlignEscapedNewlines": "DontAlign",
    "AlignOperands": "Align",
    "AlignTrailingComments": true,
    "AllowAllArgumentsOnNextLine": true,
    "AllowAllConstructorInitializersOnNextLine": true,
    "AllowAllParametersOfDeclarationOnNextLine": true,
    "AllowShortBlocksOnASingleLine": "Always",
    "AllowShortCaseLabelsOnASingleLine": true,
    "AllowShortEnumsOnASingleLine": true,
    "AllowShortFunctionsOnASingleLine": "Empty",
    "AllowShortIfStatementsOnASingleLine": "AllIfsAndElse",
    "AllowShortLambdasOnASingleLine": "Empty",
    "AllowShortLoopsOnASingleLine": true,
    "AlwaysBreakAfterDefinitionReturnType": "None",
    "AlwaysBreakAfterReturnType": "None",
    "AlwaysBreakBeforeMultilineStrings": false,
    "AlwaysBreakTemplateDeclarations": "No",
    "AttributeMacros": [
        "__capability"
    ],
    "BasedOnStyle": "LLVM",
    "BinPackArguments": true,
    "BinPackParameters": true,
    "BitFieldColonSpacing": "Both",
    "BraceWrapping": {
        "AfterCaseLabel": false,
        "AfterClass": false,
        "AfterControlStatement": "Never",
        "AfterEnum": false,
        "AfterFunction": false,
        "AfterNamespace": false,
        "AfterObjCDeclaration": false,
        "AfterStruct": false,
        "AfterUnion": false,
        "AfterExternBlock": false,
        "BeforeCatch": false,
        "BeforeElse": false,
        "BeforeLambdaBody": false,
        "BeforeWhile": false,
        "IndentBraces": false,
        "SplitEmptyFunction": true,
        "SplitEmptyRecord": true,
        "SplitEmptyNamespace": true
    },
    "BreakAfterJavaFieldAnnotations": false,
    "BreakBeforeBinaryOperators": "NonAssignment",
    "BreakBeforeBraces": "Attach",
    "BreakBeforeConceptDeclarations": false,
    "BreakBeforeInheritanceComma": false,
    "BreakBeforeTernaryOperators": true,
    "BreakConstructorInitializers": "BeforeColon",
    "BreakConstructorInitializersBeforeComma": false,
    "BreakInheritanceList": "BeforeColon",
    "BreakStringLiterals": false,
    "ColumnLimit": 0,
    "CommentPragmas": "",
    "CompactNamespaces": false,
    "ConstructorInitializerAllOnOneLineOrOnePerLine": false,
    "ConstructorInitializerIndentWidth": 2,
    "ContinuationIndentWidth": 2,
    "Cpp11BracedListStyle": false,
    "DeriveLineEnding": true,
    "DerivePointerAlignment": true,
    "DisableFormat": false,
    "EmptyLineAfterAccessModifier": "Leave",
    "EmptyLineBeforeAccessModifier": "Leave",
    "ExperimentalAutoDetectBinPacking": false,
    "FixNamespaceComments": false,
    "ForEachMacros": [
        "foreach",
        "Q_FOREACH",
        "BOOST_FOREACH"
    ],
    "IfMacros": [
        "KJ_IF_MAYBE"
    ],
    "IncludeBlocks": "Preserve",
    "IncludeCategories": [
        {
            "Regex": "^\"(llvm|llvm-c|clang|clang-c)/",
            "Priority": 2,
            "SortPriority": 0,
            "CaseSensitive": false
        },
        {
            "Regex": "^(<|\"(gtest|gmock|isl|json)/)",
            "Priority": 3,
            "SortPriority": 0,
            "CaseSensitive": false
        },
        {
            "Regex": ".*",
            "Priority": 1,
            "SortPriority": 0,
            "CaseSensitive": false
        }
    ],
    "IncludeIsMainRegex": "",
    "IncludeIsMainSourceRegex": "",
    "IndentAccessModifiers": false,
    "IndentCaseBlocks": true,
    "IndentCaseLabels": true,
    "IndentExternBlock": "Indent",
    "IndentGotoLabels": false,
    "IndentPPDirectives": "None",
    "IndentRequires": true,
    "IndentWidth": 2,
    "IndentWrappedFunctionNames": false,
    "InsertTrailingCommas": "None",
    "JavaScriptQuotes": "Leave",
    "JavaScriptWrapImports": true,
    "KeepEmptyLinesAtTheStartOfBlocks": true,
    "LambdaBodyIndentation": "Signature",
    "Language": "Cpp",
    "MacroBlockBegin": "",
    "MacroBlockEnd": "",
    "MaxEmptyLinesToKeep": 100000,
    "NamespaceIndentation": "None",
    "ObjCBinPackProtocolList": "Auto",
    "ObjCBlockIndentWidth": 2,
    "ObjCBreakBeforeNestedBlockParam": true,
    "ObjCSpaceAfterProperty": false,
    "ObjCSpaceBeforeProtocolList": true,
    "PPIndentWidth": -1,
    "PackConstructorInitializers": "BinPack",
    "PenaltyBreakAssignment": 1,
    "PenaltyBreakBeforeFirstCallParameter": 1,
    "PenaltyBreakComment": 1,
    "PenaltyBreakFirstLessLess": 1,
    "PenaltyBreakOpenParenthesis": 1,
    "PenaltyBreakString": 1,
    "PenaltyBreakTemplateDeclaration": 1,
    "PenaltyExcessCharacter": 1,
    "PenaltyIndentedWhitespace": 1,
    "PenaltyReturnTypeOnItsOwnLine": 1,
    "PointerAlignment": "Right",
    "QualifierAlignment": "Leave",
    "ReferenceAlignment": "Pointer",
    "ReflowComments": false,
    "RemoveBracesLLVM": false,
    "SeparateDefinitionBlocks": "Leave",
    "ShortNamespaceLines": 0,
    "SortIncludes": "Never",
    "SortJavaStaticImport": "Before",
    "SortUsingDeclarations": false,
    "SpaceAfterCStyleCast": false,
    "SpaceAfterLogicalNot": false,
    "SpaceAfterTemplateKeyword": false,
    "SpaceAroundPointerQualifiers": "Default",
    "SpaceBeforeAssignmentOperators": true,
    "SpaceBeforeCaseColon": false,
    "SpaceBeforeCpp11BracedList": false,
    "SpaceBeforeCtorInitializerColon": true,
    "SpaceBeforeInheritanceColon": true,
    "SpaceBeforeParens": "ControlStatements",
    "SpaceBeforeParensOptions": {
        "AfterControlStatements": true,
        "AfterForeachMacros": true,
        "AfterFunctionDefinitionName": false,
        "AfterFunctionDeclarationName": false,
        "AfterIfMacros": true,
        "AfterOverloadedOperator": false,
        "BeforeNonEmptyParentheses": false
    },
    "SpaceBeforeRangeBasedForLoopColon": true,
    "SpaceBeforeSquareBrackets": false,
    "SpaceInEmptyBlock": false,
    "SpaceInEmptyParentheses": false,
    "SpacesBeforeTrailingComments": 2,
    "SpacesInAngles": "Leave",
    "SpacesInCStyleCastParentheses": false,
    "SpacesInConditionalStatement": false,
    "SpacesInContainerLiterals": false,
    "SpacesInLineCommentPrefix": {
        "Minimum": 0,
        "Maximum": -1
    },
    "SpacesInParentheses": false,
    "SpacesInSquareBrackets": false,
    "Standard": "Auto",
    "StatementAttributeLikeMacros": [
        "Q_EMIT"
    ],
    "StatementMacros": [
        "Q_UNUSED",
        "QT_REQUIRE_VERSION"
    ],
    "TabWidth": 2,
    "UseCRLF": false,
    "UseTab": "Never",
    "WhitespaceSensitiveMacros": [
        "STRINGIZE",
        "PP_STRINGIZE",
        "BOOST_PP_STRINGIZE",
        "NS_SWIFT_NAME",
        "CF_SWIFT_NAME"
    ]
}

@per1234
Copy link
Contributor Author

per1234 commented Aug 16, 2022

Thanks so much @kittaakos. That approach is ideal for facilitating the maintenance of the formatter configuration.

I have now updated the PR according to your suggestions:

https://github.com/arduino/arduino-ide/compare/0719836e98c37634817a8b63cb004a8f6c933bd6..923f5c6b4e7cc8b6558b8580ca9ef999ebfef497

…onfiguration

The Arduino IDE's "Auto Format" feature is configured to produce the standard Arduino sketch formatting style by
default.

The Arduino IDE editor's default settings are compliant with that style. However, the user may adjust the editor
settings. In this case, the Arduino IDE automatically adjusts the Auto Format configuration to align with the user's
preferences.

The formatter configuration is consumed by several other projects in addition to the Arduino IDE. For this reason, the
configuration is hosted and maintained in a centralized location, from which it is pulled by all projects that use it.

Previously, the adjustment of the Arduino IDE formatter configuration according to the editor settings was integrated
into the configuration object itself. This meant that the standardized configuration had to be modified each time it was
pulled in to sync from the upstream source.

Moving the base formatter configuration object to a dedicated file, separated from the handling and adjustment code
allows syncs to be done by simply replacing the existing configuration file with the one automatically generated by the
CI system of the repository where the source configuration is hosted.
@per1234 per1234 marked this pull request as draft August 16, 2022 11:40
@@ -147,189 +147,10 @@ function styleJson({
UseTab,
}: ClangFormatOptions): Record<string, unknown> {
// Source: https://github.com/arduino/tooling-project-assets/tree/main/other/clang-format-configuration
const defaultConfig = require('./default-formatter-config.json'); // 1. require the JSON
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line should be changed to, it's my fault. I found it only when verifying the behavior:

const defaultConfig = require('../../src/node/default-formatter-config.json');

Explanation:

We write TS code that will be transpiled to JS code. IDE2 does not run TS code, only JS code. The sources (TS files, JSON, .etc) are in src, the transpiled JS code is in lib.

The TS sources and the JSON config are here:

arduino-ide-extension/src/node/clang-formatter.ts
arduino-ide-extension/src/node/default-formatter-config.json

The TS code will be JS, and the module location will be these:

arduino-ide-extension/lib/node/clang-formatter.d.ts
arduino-ide-extension/lib/node/clang-formatter.d.ts.map
arduino-ide-extension/lib/node/clang-formatter.js

Notice the src and lib differences in the path. JSON files will remain in src at runtime, JS files will be in lib folder. To be able to require the JSON file from the transpiled JS, the require path must be changed from ./default-formatter-config.json to ../../src/node/default-formatter-config.json. If this is not clear, please let me know.

Also, please remove the // 1. require the JSON and the // 2. override the default values with the user-defined ones comments. I added them for explanation purposes.

Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line should be changed

Thanks. I have done it here: becb901

JSON files will remain in src at runtime, JS files will be in lib folder.

I saw that when I went to test the build (I think I somehow ended up still old source code when I ran it from source).

I was going down the path mentioned here:

https://stackoverflow.com/a/53629381/7059512

(adding something like "src/node/*.json" to the include field of tsconfig.json)

please remove the // 1. require the JSON and the // 2. override the default values with the user-defined ones comments.

OK, done here: aff3560

@per1234 per1234 marked this pull request as ready for review August 16, 2022 14:29
@kittaakos kittaakos self-requested a review August 16, 2022 15:05
Copy link
Contributor

@kittaakos kittaakos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's working very nicely. Thank you!


verified.mp4

@per1234 per1234 merged commit 9e2b73a into arduino:main Aug 16, 2022
@per1234 per1234 deleted the standardize-formatter-config branch August 16, 2022 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: enhancement Proposed improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants